using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using JetBrains.Annotations;
using Newtonsoft.Json.Linq;
using UnityEngine;

public class GameSystem : MonoBehaviour
{
    GameManager gameManager;
    bool online = false;
    string online_world_id;

    TcpClient tcpClient;
    UdpClient udpClient;
    Thread thread_frame_sync;

    public GameObject charactor;
    public GameObject ui_message_obj;
    UI_Message ui_Message;
    Dictionary<String, GameObject> players = new Dictionary<string, GameObject>();
    List<string> player_names = new List<string>();
    JObject real_time_frame = new JObject();
    // Start is called before the first frame update
    void Start()
    {
        ui_Message = ui_message_obj.GetComponent<UI_Message>();
        gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
        GameObject prefabInstance = Instantiate(charactor);
        prefabInstance.name = gameManager.user;
        prefabInstance.GetComponent<PlayerController>().gameManager = gameManager;
        prefabInstance.transform.parent = GameObject.Find("Players").transform;
        players.Add(gameManager.user, prefabInstance);
        player_names.Add(gameManager.user);
    }

    void OnDestroy()
    {
        if (tcpClient != null) tcpClient.Close();
        if (udpClient != null) udpClient.Close();
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        if (online)
        {
            if (tcpClient.Connected)
            {
                //发送玩家信息帧
                JObject jobject = new JObject();
                jobject["action"] = "send_frame";
                jobject["user"] = gameManager.user;
                jobject["world_id"] = int.Parse(online_world_id);
                JObject frame = new JObject();
                frame["frame_input"] = players[gameManager.user].GetComponent<PlayerController>().frame_input;
                frame["frame_info"] = players[gameManager.user].GetComponent<PlayerController>().frame_info;
                jobject["frame"] = frame;
                udpClient.Send(
                    Encoding.UTF8.GetBytes(jobject.ToString()),
                    Encoding.UTF8.GetBytes(jobject.ToString()).Length,
                    new IPEndPoint(IPAddress.Parse(gameManager.server_address), gameManager.server_udp_port)
                );

                //更新玩家帧 检查是否缺少玩家
                for (int i = 0; i < player_names.Count; i++)
                {
                    if (player_names[i] != gameManager.user)
                    {
                        //创造玩家
                        if (!players.ContainsKey(player_names[i]))
                        {
                            print("缺少玩家:" + player_names[i]);
                            CreatePlayer(player_names[i]);
                            players[player_names[i]].GetComponent<PlayerController>().frame_input = (JObject)real_time_frame["frame"][player_names[i]]["frame_input"];
                            players[player_names[i]].GetComponent<PlayerController>().frame_info = (JObject)real_time_frame["frame"][player_names[i]]["frame_info"];
                            players[player_names[i]].GetComponent<PlayerController>().InfoSync();
                        }
                        else
                        {
                            players[player_names[i]].GetComponent<PlayerController>().frame_input = (JObject)real_time_frame["frame"][player_names[i]]["frame_input"];
                            players[player_names[i]].GetComponent<PlayerController>().frame_info = (JObject)real_time_frame["frame"][player_names[i]]["frame_info"];
                            players[player_names[i]].GetComponent<PlayerController>().InfoSync();
                        }
                    }
                }

                //检查多余玩家
                foreach (string str in players.Keys)
                {
                    if (!player_names.Contains(str) && str != gameManager.user)
                    {
                        DelectPlayer(str);
                        break;
                    }
                }
            }
            else
            {
                //tcp终止
                try
                {
                    tcpClient = new TcpClient(gameManager.server_address, gameManager.server_tcp_port);
                }
                catch (SocketException e)
                {
                    ui_Message.Show(e + "");
                }
                JObject jObject = new JObject();
                jObject["action"] = "relink";
                jObject["user"] = gameManager.user;
                jObject["world_id"] = int.Parse(online_world_id);
                string message = jObject.ToString();
                byte[] bytes = Encoding.UTF8.GetBytes(message);
                NetworkStream stream = tcpClient.GetStream();
                stream.Write(bytes, 0, bytes.Length);
                // print("Message send to Java Server:" + bytes);

                // 接收来自Java服务器的响应消息
                byte[] buffer = new byte[10240];
                int bytesRead = stream.Read(buffer, 0, buffer.Length);
                string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                print("Received response from Java server: " + response);
            }
        }
    }

    public void JoinInOnline()
    {
        if (!online)
        {
            print(gameManager.user + " try to join in online.");
            try
            {
                tcpClient = new TcpClient(gameManager.server_address, gameManager.server_tcp_port);
            }
            catch (SocketException e)
            {
                ui_Message.Show(e + "");
            }
            udpClient = new UdpClient();

            JObject jObject = new JObject();
            jObject["action"] = "join";
            jObject["user"] = gameManager.user;
            string message = jObject.ToString();
            byte[] bytes = Encoding.UTF8.GetBytes(message);
            NetworkStream stream = tcpClient.GetStream();
            stream.Write(bytes, 0, bytes.Length);
            // print("Message send to Java Server:" + bytes);

            // 接收来自Java服务器的响应消息
            byte[] buffer = new byte[1024];
            int bytesRead = stream.Read(buffer, 0, buffer.Length);
            string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
            print("Received response from Java server: " + response);
            try
            {
                JObject jObject0 = JObject.Parse(response);
                switch ((string)jObject0["response"])
                {
                    case "success":
                        {
                            online_world_id = (string)jObject0["world_id"];
                            thread_frame_sync = new Thread(Response);
                            thread_frame_sync.Start();
                            online = true;
                            break;
                        }
                    case "server full":
                        {
                            break;
                        }
                }
            }
            catch (Exception e)
            {
                print(e);
            }
        }
        else
        {

        }
    }

    void CreatePlayer(string name)
    {
        GameObject prefabInstance = Instantiate(charactor);
        prefabInstance.name = name;
        prefabInstance.GetComponent<PlayerController>().gameManager = gameManager;
        prefabInstance.transform.parent = GameObject.Find("Players").transform;
        players[name] = prefabInstance;
    }

    void DelectPlayer(string name)
    {
        Destroy(players[name]);
        players.Remove(name);
    }

    void Response()
    {
        while (true)
        {
            if (tcpClient.Connected)
            {
                // 接收来自Java服务器的响应消息
                NetworkStream stream = tcpClient.GetStream();
                byte[] buffer = new byte[10240];
                int bytesRead = stream.Read(buffer, 0, buffer.Length);
                string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                response = FormatJsonString(response);
                print("Received response from Java server: " + response);

                try
                {
                    JObject jObj = JObject.Parse(response);
                    switch ((string)jObj["action"])
                    {
                        case "frame_sync":
                            {
                                this.real_time_frame = (JObject)jObj["real_time_frame"];
                                JObject frame = (JObject)real_time_frame["frame"];
                                IEnumerable<JProperty> properties = frame.Properties();
                                List<string> frame_player_list = new List<string>();
                                foreach (JProperty item in properties)
                                {
                                    // item.Name 为 键
                                    // item.Value 为 值
                                    frame_player_list.Add(item.Name);
                                    if (item.Name != gameManager.user)
                                    {
                                        string player = item.Name;
                                        if (!players.ContainsKey(player))
                                        {
                                            player_names.Add(item.Name);
                                        }
                                    }
                                }
                                foreach (string player in player_names)
                                {
                                    if (!frame_player_list.Contains(player))
                                    {
                                        player_names.Remove(player);
                                    }
                                }
                                break;
                            }
                    }
                }
                catch (Exception e)
                {
                    print(e);
                }
            }
        }
    }

    public GameManager getGameManager()
    {
        return gameManager;
    }

    string FormatJsonString(string response)
    {
        int braceCount = 0;
        int endIndex = -1;
        for (int i = 0; i < response.Length; i++)
        {
            if (response[i] == '{')
            {
                braceCount++;
            }
            else if (response[i] == '}')
            {
                braceCount--;
                if (braceCount == 0)
                {
                    endIndex = i;
                    break;
                }
            }
        }
        // 截取第一个完整的 JSON 对象
        string firstJsonObject = response.Substring(0, endIndex + 1);
        return firstJsonObject;
    }
}
